pgvector + Gemini nano in Chromeで作る、ブラウザ内RAGシステムの実装

pgvector + Gemini nano in Chromeで作る、ブラウザ内RAGシステムの実装

Clock Icon2025.01.22

Introduction

以前PGliteとClaude APIをつかってクライアントだけでRAGするという記事を書きました。
この記事では、WASM版PostgreSQLのPGliteをクライアントサイドで使用し、
Claude APIもクライアントサイドのjavascriptで直接呼び出すことでサーバを使用せずRAGを実現しました。
しかしこの手法では、Claude APIを使うためにアクセスキーを直接扱う必要があるので少々問題があります。

なんとかならないかと思っていたところ、ChromeでGeminiが動くとの情報。
DevとかCanaryでは以前から動いてたみたいですが、最近はStable版のChromeでも動く様子。
また、Chrome v132から日本語も使えるようになり、使えそうだったので試してみました。

Environment

今回のデモを実行するための環境は以下の通りです。

  • MacBook Pro (14-inch, M3, 2023)
  • OS : MacOS 14.5
  • Chrome : 132.0.6834.84(Official Build)(arm64)

Setup

まずはGemini nanoが使えるようにChromeの設定をします。
Chromeでchrome://flagsを開き、

  • Enables optimization guide on deviceを「Enabled BypassPerfRequirement」に変更
  • Prompt API for Gemini Nanoを「Enabled」に変更

次に、chrome://componentsを開いて、「Optimization Guide On Device Model」をアップデートします。

もし「Optimization Guide On Device Model」の項目がない場合、
devtoolを開いてコンソールに「await ai.languageModel.create();」と入力し(たぶんエラーが出ます)、
再度chrome://componentsを確認してみてください。

なお、ここにやり方が詳細にのってます。

Try

では試してみます。
この記事にあるRAGデモをベースに、
AnthoropicのAPIを実行している箇所をGemini nanoに変更します。

コード構造は以下のような感じです。
(pglite.wasmなどは前の記事と同じようにコピーしておく)

src
├── utils
│   └── constants.js
├── styles
│   └── App.css
├── components
│   ├── SearchForm.jsx
│   ├── DocumentsSetup.jsx
│   └── ResultDisplay.jsx
├── main.jsx
├── App.jsx
└── services
    ├── databaseOperations.js
    ├── vectorOperations.js
    └── aiOperations.js

ファイル内容をみてみましょう。

データベースセットアップ

src/services/databaseOperations.js では、pgvector拡張を使ってデータを登録します。
RAGデモということで、以下のような、架空の惑星情報をpgliteに登録します。

//src/utils/constants.js
export const DOCUMENTS = [
  {
    id: 1,
    content: `
      Grimlorは2027年に発見された新しい系外惑星。
      恒星MZX-405を公転しており、Alpha Velorium星系に属する。
      2035年に最初の有人着陸が行われたが、大気中の酸素濃度は非常に低く、
      特殊な酸素生成装置を使わないと人間は長期滞在できない。
      地表温度は平均で-60℃程度だが、一部地域では
      地熱活動により+10℃に達するエリアもある。
    `
  },

・・・

];

検索処理

ユーザーがSearchFormコンポーネントで質問を入力すると、
pgvectorによる類似度検索が実行されます。
検索結果をaiOperations.jsのgetAIResponse関数で、
Gemini nanoに渡して回答を生成します。

Gemini nanoの使い方はシンプルです。
getAIResponseでは最初にGemini nanoが使えるかチェックしてます。

  const capabilities = await window.ai.languageModel.capabilities();
  if (!capabilities.available) {
    throw new Error('AI model is not available on this browser.');
  }

その後createでSessionを作成して、prompt関数で回答を取得しています。

  const aiSession = await window.ai.languageModel.create({
    systemPrompt
  });

  const response = await aiSession.prompt(userPrompt);
  console.log('AI response generated successfully');
  return response;

動作確認

buildして起動し、動かしてみましょう。

% npm run build

> pglite-react-app@0.0.0 build
> vite build
・・・
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.
✓ built in 843ms

% npm run dev

> pglite-react-app@0.0.0 dev
> vite


  VITE v5.4.2  ready in 77 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

データベースセットアップボタンを押してデータを登録したあと、
質問をするとpgliteのデータを参照してGemini nanoが回答してくれます。
(少々時間がかかります)

gemini-nano-sc1.png

Summary

今回はクライアントサイドだけでRAGを実現するということで、
pgliteとGemini nanoをつかって実装してみました。
外部APIやサーバを使わず、クライアントサイドのDBとLLMだけで動いているのは結構すごいですね。
今後モデルがバージョンアップされていけば速度や性能もどんどんあがっていくので、
より使えるようになってくると思います。

References

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.